package com.offcn.seckill.timer;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.offcn.common.utils.DateUtil;
import com.offcn.seckill.mapper.SeckillGoodsMapper;
import com.offcn.seckill.pojo.SeckillGoods;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * 定时任务方法配置
 *
 * @author 秋林
 * @date 2022/10/18 17:45:28
 */
@Component
public class SeckillGoodsPushTask {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    SeckillGoodsMapper seckillGoodsMapper;

    /**
     * 每30秒执行一次
     */
    @Scheduled(cron = "0/30 * * * * ?")
    public void loadGoodsPushRedis() {
        //获得时间段集合
        List<Date> dateMenus = DateUtil.getDateMenus();

        /*
           循环时间段集合 从0点起算，美2个小时一个时段，一天可以分12个字段，本次客户要求只显示5个时段的活动的商品(包含正在秒杀和即将开始的商品), 故以当前时间段为参照，寻找5个活动时段;
           比如：当前时间为15点，dateMenus的值为{14,16,18,20,22}
           注：15点进入活动页面的客户应该也能看到14~16这个时段秒杀的商品，即正在秒杀的商品
         */

        // 寻找符合每个活动时段的商品, 存入redis以展示在页面
        for (Date startTime : dateMenus) {
            //提取开启时间，转换为年月日格斯的字符串
            String extName = DateUtil.date2Str(startTime);

            //创建查询条件对象
            QueryWrapper<SeckillGoods> queryWrapper = new QueryWrapper<>();

            //设置查询条件对象
            //1.商品必须审核通过  status = 1
            queryWrapper.eq("status", "1");
            //2.库存大于0
            queryWrapper.gt("stock_count", 0);
            //3.数据库中商品秒杀开始时间 >= 本轮活动的开始时间
            queryWrapper.ge("start_time", DateUtil.date2StrFull(startTime));
            //4.数据库中商品秒杀结束时间 < 本轮活动时段的开始 +2小时，即活动的结束时间
            queryWrapper.lt("end_time", DateUtil.date2StrFull(DateUtil.addDateHour(startTime, 2)));            /*
              5.判断redis中是否已缓存过此商品
                若没有缓存则添加缓存，并设置2小时后子欧诺个删除，因为整个秒杀时间段就两个小时
                若缓存过就不再覆盖缓存，否则会覆盖掉库存等消息，导致秒杀扣减的库存由被初始了回来
             */
            Set keys = redisTemplate.boundHashOps("SeckillGoods_" + extName).keys();

            //判断keys是否不为空，就设置排除条件
            if (!StringUtils.isEmpty(keys) && keys.size() > 0) {
                queryWrapper.notIn("id", keys);
            }

            //查询符合条件的数据
            List<SeckillGoods> seckillGoodsList = seckillGoodsMapper.selectList(queryWrapper);
            System.out.println("符合条件的数据: "+seckillGoodsList);

            //遍历查询到的数据集合，存储数据到redis
            for (SeckillGoods seckillGoods : seckillGoodsList) {
                redisTemplate.boundHashOps("SeckillGoods_" + extName).put(seckillGoods.getId(), seckillGoods);

                //设置超时时间2小时
                redisTemplate.expireAt("SeckillGoods_" + extName, DateUtil.addDateHour(startTime, 2));
            }
        }


    }

    /**
     * 将商品ID存入到数组中
     *
     * @param len 长度
     * @param id  值
     * @return {@link Long[]}
     */
    public Long[] pushIds(int len , Long id){
        Long[] ids = new Long[len];
        for (int i = 0; i < ids.length; i++) {
            ids[i]=id;
        }
        return ids;
    }
}
